package swt.screen;

import java.io.IOException;
import java.util.Date;
import java.util.logging.Logger;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import swt.action.CountdownAction;
import swt.commons.Const;
import swt.commons.LogUtil;
import swt.commons.ResourceUtil;
import swt.commons.Utils;
import swt.tray.SysTray;

import com.swtdesigner.SWTResourceManager;

public class AutoShutdownSetup {

	private static Logger log = LogUtil.getLogger();
	
	private Text txtYmd;
	private Text txtShutdownMM;
	private Text txtShutdownHH;
	private Button btnSetup;
	private Button btnHide;
	protected Shell shell;
	private Button chkEdit;
	private CLabel clblNow;
	private Group group;
	private CLabel clblDay;
	private Label setupPasswordLink;
	private CLabel clblTime;
	
	private String hour;
	private String minute;
	private String day;
	private boolean setupBtnClickFlag = false;
	private String language; 
	private CountdownAction countdown;
	
	/**
	 * Constructor
	 * @param day
	 * @param hour
	 * @param minute
	 */
	public AutoShutdownSetup(String day, String hour, String minute){
		this.day = day;
		this.hour = hour;
		this.minute = minute;
	}

	/**
	 * Open the dialog
	 * @return the result
	 */
	public boolean open(){
		try {
			ResourceUtil resourceUtil = ResourceUtil.getInstance();
			language = resourceUtil.getProperty(Const.KEY_LANGUAGE);
			// Setup language
			if (Utils.isNullEmpty(language)) {
				language = Const.LANGUAGE_EN;
				resourceUtil.setProperty(Const.KEY_LANGUAGE, language);
			}
			// Open screen
			final Display display = Display.getDefault();
			createContents();
			shell.open();
			shell.layout();
			initData();
			while (!shell.isDisposed()) {
				if (!display.readAndDispatch())
					display.sleep();
			}
			display.dispose();
		} 
		catch (Exception e) {
			log.severe("Exception." + e.getMessage());
		}
		return true;
	}

	/**
	 * Create contents of the dialog
	 * @throws IOException 
	 */
	protected void createContents() throws IOException {
		
		shell = new Shell(SWT.TITLE | SWT.PRIMARY_MODAL | SWT.BORDER | SWT.CLOSE);
		shell.setSize(500, 277);
		shell.setImage(SWTResourceManager.getImage(Const.ICON_FILE));
		shell.addShellListener(new ShellAdapter(){
			public void shellClosed(ShellEvent e) {
				e.doit = false;
				exitAction();
			}
		});
		
		Rectangle disRect = Display.getCurrent().getBounds();
		int x = (disRect.width - shell.getSize().x) / 2;
		int y = (disRect.height - shell.getSize().y) / 2;
		shell.setLocation(x,y);

		clblNow = new CLabel(shell, SWT.SHADOW_OUT | SWT.CENTER);
		clblNow.setBounds(35, 23, 100, 23);
		clblNow.setFont(Const.FONT_BASE);
		clblNow.setBackground(SWTResourceManager.getColor(244, 245, 255));

		final DigitalClock clock = new DigitalClock(this.shell, 
				SWT.NONE, new Point(196, 26), 
				SWTResourceManager.getFont("Microsoft Sans Serif", 11, SWT.BOLD), 
				SWTResourceManager.getColor(244, 245, 255), 
				SWTResourceManager.getColor(0, 0, 255));
		clock.setBounds(140, 21, 196, 26);
		clock.setBorder(true);
		clock.setDisplayDateFlag(false);
		clock.start();

		String[] supportLang = Const.LANGUAGE_ALL.split("\\|");
		int startX = 435;
		int startY = 10;
		int width = 20;
		for (int i = 0; i < supportLang.length; i++) {
			if (i > 0) {
				final Label label = new Label(shell, SWT.NONE);
				label.setText("|");
				label.setBounds(startX, startY, 7, 23);
				startX += 7;
			}
			final Label lang = new Label(shell, SWT.NONE);
			lang.setBounds(startX, startY, width, 23);
			lang.setText(supportLang[i]);
			startX += width;
			lang.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
			lang.setForeground(SWTResourceManager.getColor(0, 0, 255));
			lang.addMouseTrackListener(new MouseTrackAdapter() {
				Display display = Display.getCurrent();
				public void mouseEnter(MouseEvent e) {
					display.syncExec(new Runnable() {
						public void run() {
							lang.setForeground(SWTResourceManager.getColor(0, 0, 170));
						}
					});
				}
				public void mouseExit(MouseEvent arg0) {
					display.syncExec(new Runnable() {
						public void run() {
							lang.setForeground(SWTResourceManager.getColor(0, 0, 255));
						}
					});
				}
			});
			lang.addMouseListener(new MouseAdapter() {
				public void mouseDown(MouseEvent arg0) {
					try {
						language = lang.getText();
						ResourceUtil.getInstance().setProperty(Const.KEY_LANGUAGE, language);
						setDisplayControlLabel();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			});
		}
		
		group = new Group(shell, SWT.NONE);
		group.setBounds(10, 73, 474, 160);

		clblDay = new CLabel(group, SWT.SHADOW_OUT | SWT.CENTER);
		clblDay.setBounds(25, 33, 100, 23);
		clblDay.setFont(Const.FONT_BASE);
		clblDay.setBackground(SWTResourceManager.getColor(244, 245, 255));

		txtYmd = new Text(group, SWT.CENTER | SWT.BORDER);
		txtYmd.addFocusListener(new FocusAdapter() {
			public void focusGained(final FocusEvent arg0) {
				if (txtYmd.getEditable()){
					txtYmd.selectAll();
				}
			}
			public void focusLost(final FocusEvent arg0) {
				if (txtYmd.getEditable()){
					if (!Utils.isNullEmpty(txtYmd.getText())){
						txtYmd.setText(Utils.formatYYYYMMDD(txtYmd.getText().trim()));
					}
				}
			}
		});
		txtYmd.setEditable(false);
		txtYmd.setBounds(131, 33, 100, 23);
		txtYmd.setTextLimit(10);
		txtYmd.setForeground(SWTResourceManager.getColor(0, 0, 255));
		txtYmd.setFont(SWTResourceManager.getFont("Microsoft Sans Serif", 11, SWT.NORMAL));
		txtYmd.setBackground(Const.COLOR_BGR_LABEL);

		chkEdit = new Button(group, SWT.CHECK);
		chkEdit.setBounds(245, 38, 80, 16);
		chkEdit.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent arg0) {
				if (chkEdit.getSelection() == true){
					stopCountdown();
					//
					txtYmd.setEditable(true);
					txtYmd.setBackground(Const.COLOR_TEXT_MUST_INPUT);
					txtYmd.setFocus();
					txtYmd.selectAll();
				}
				else{
					startCountdown();
					//
					txtYmd.setEditable(false);
					txtYmd.setBackground(Const.COLOR_BGR_LABEL);
					if (txtShutdownHH.getEditable()) {
						txtShutdownHH.setFocus();
					}
				}
			}
		});
		
		setupPasswordLink = new Label(group, SWT.NONE);
		setupPasswordLink.setBounds(325, 38, 120, 16);
		setupPasswordLink.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
		setupPasswordLink.setForeground(SWTResourceManager.getColor(0, 0, 255));
		setupPasswordLink.addMouseTrackListener(new MouseTrackAdapter() {
			Display display = Display.getCurrent();
			public void mouseEnter(MouseEvent e) {
				display.syncExec(new Runnable() {
					public void run() {
						setupPasswordLink.setForeground(SWTResourceManager.getColor(0, 0, 170));
					}
				});
			}
			public void mouseExit(MouseEvent arg0) {
				display.syncExec(new Runnable() {
					public void run() {
						setupPasswordLink.setForeground(SWTResourceManager.getColor(0, 0, 255));
					}
				});
			}
		});
		setupPasswordLink.addMouseListener(new MouseAdapter() {
			public void mouseDown(MouseEvent arg0) {
				openSetupPasswordWindow();
			}
		});

		clblTime = new CLabel(group, SWT.SHADOW_OUT | SWT.CENTER);
		clblTime.setBounds(25, 80, 100, 23);
		clblTime.setFont(Const.FONT_BASE);
		clblTime.setBackground(SWTResourceManager.getColor(244, 245, 255));

		txtShutdownHH = new Text(group, SWT.CENTER | SWT.BORDER);
		txtShutdownHH.setForeground(SWTResourceManager.getColor(0, 0, 255));
		txtShutdownHH.setBounds(131, 80, 72, 23);
		txtShutdownHH.setTextLimit(2);
		txtShutdownHH.setFont(SWTResourceManager.getFont("Microsoft Sans Serif", 11, SWT.BOLD));
		txtShutdownHH.setBackground(Const.COLOR_TEXT_MUST_INPUT);
		txtShutdownHH.setTabs(0);
		txtShutdownHH.addFocusListener(new FocusAdapter() {
			public void focusGained(final FocusEvent arg0) {
				txtShutdownHH.selectAll();
			}
			public void focusLost(final FocusEvent arg0) {
				if (txtShutdownHH.getText().trim().length() == 1){
					String str = Utils.addLeft(txtShutdownHH.getText(), "0", 2);
					txtShutdownHH.setText(str);
				}
			}
		});

		final Label label = new Label(group, SWT.NONE);
		label.setFont(SWTResourceManager.getFont("Showcard Gothic", 12, SWT.BOLD));
		label.setText(":");
		label.setBounds(222, 80, 17, 23);
		
		txtShutdownMM = new Text(group, SWT.CENTER | SWT.BORDER);
		txtShutdownMM.setForeground(SWTResourceManager.getColor(0, 0, 255));
		txtShutdownMM.setBounds(245, 80, 72, 23);
		txtShutdownMM.setTextLimit(2);
		txtShutdownMM.setFont(SWTResourceManager.getFont("Microsoft Sans Serif", 11, SWT.BOLD));
		txtShutdownMM.setBackground(Const.COLOR_TEXT_MUST_INPUT);
		txtShutdownHH.setTabs(1);
		txtShutdownMM.addFocusListener(new FocusAdapter() {
			public void focusGained(final FocusEvent arg0) {
				txtShutdownMM.selectAll();
			}
			public void focusLost(final FocusEvent arg0) {
				if (txtShutdownMM.getText().trim().length() == 1){
					String str = Utils.addLeft(txtShutdownMM.getText(), "0", 2);
					txtShutdownMM.setText(str);
				}
			}
		});

		btnSetup = new Button(group, SWT.NONE);
		btnSetup.setBounds(100, 120, 120, 25);
		btnSetup.setFont(Const.FONT_BASE);
		btnSetup.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent arg0) {
				setupBtnClickFlag = !setupBtnClickFlag;
				try {
					setupAction();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		});
		
		btnHide = new Button(group, SWT.NONE);
		btnHide.setBounds(250, 120, 120, 25);
		btnHide.setFont(Const.FONT_BASE);
		btnHide.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent arg0) {
				hideAction();
			}
		});
		//
		shell.setDefaultButton(btnSetup);
		// Set display label of Controls
		setDisplayControlLabel();
	}

	/**
	 * Set display language
	 * @param language
	 * @throws IOException
	 */
	private void setDisplayControlLabel() throws IOException {
		if (language.equals(Const.LANGUAGE_EN)) {
			shell.setText("Auto Shutdown - Setup shutdown timer");
			clblNow.setText("Now");
			group.setText("Shutdown timer");
			clblDay.setText("Day");
			chkEdit.setText("Change");
			setupPasswordLink.setText("*Setup password");
			clblTime.setText("Timer");
			btnHide.setText("Hide");
			if (setupBtnClickFlag) {
				btnSetup.setText("Change");
			}
			else {
				btnSetup.setText("Set");
			}
			btnHide.setToolTipText("Hide to system tray.");
			btnSetup.setToolTipText("Save setup time.");
		}
		else if (language.equals(Const.LANGUAGE_VN)) {
			shell.setText("Auto Shutdown - Thiết lập giờ tắt máy");
			clblNow.setText("Bây giờ là");
			group.setText("Giờ tắt máy");
			clblDay.setText("Ngày");
			chkEdit.setText("Đổi ngày");
			setupPasswordLink.setText("*Thiết lập mật khẩu");
			clblTime.setText("Giờ");
			btnHide.setText("Ẩn chương trình");
			if (setupBtnClickFlag) {
				btnSetup.setText("Thiết lập lại");
			}
			else {
				btnSetup.setText("Thiết lập");
			}
			btnHide.setToolTipText("Ẩn chương trình xuống khay hệ thống.");
			btnSetup.setToolTipText("Lưu cài đặt.");
		}
	}

	/**
	 * initData
	 *
	 */
	private void initData() {
		if (!Utils.isNullEmpty(this.hour)){
			txtShutdownHH.setText(this.hour);
		}
		if (!Utils.isNullEmpty(this.minute)){
			txtShutdownMM.setText(this.minute);
		}
		if (!Utils.isNullEmpty(this.day)){
			txtYmd.setText(this.day);
		}
		else{
			String today = Utils.formatDate(new Date(), Const.DATE_FORMAT);
			txtYmd.setText(today);
		}
		//
		txtShutdownHH.setFocus();
	}

	/**
	 * openSetupPasswordWindow
	 *
	 */
	private void openSetupPasswordWindow() {
		log.info("Open Password Setup Screen clicked");
		
		stopCountdown();
		
		SetupPasswordWindow window = new SetupPasswordWindow(this.shell, Const.SETUP_PASS);
		window.open();
	}
	
	/**
	 * close action
	 *
	 */
	private void exitAction() {
		ResourceUtil resourceUtil = ResourceUtil.getInstance();
		String language = resourceUtil.getProperty(Const.KEY_LANGUAGE);
		String msg = "";
		if (language.equals(Const.LANGUAGE_EN)) {
			msg = "Exit program?";
		}
		else if (language.equals(Const.LANGUAGE_VN)) {
			msg = "Thoát chương trình?";
		}
		if (Utils.confirmMsgBox(msg) == SWT.YES) {
			stopCountdown();
			//
			shell.dispose();
			log.info("App exit.");
		}
	}
	
	/**
	 * setup Action
	 * @throws IOException 
	 *
	 */
	private void setupAction() throws IOException {
		if (setupBtnClickFlag) {
			if (!checkInput()){
				setupBtnClickFlag = !setupBtnClickFlag;
				return;
			}
			chkEdit.setEnabled(false);
			chkEdit.setSelection(false);
			txtYmd.setEditable(false);
			txtShutdownHH.setEditable(false);
			txtShutdownMM.setEditable(false);
			txtYmd.setBackground(Const.COLOR_BGR_LABEL);
			txtShutdownHH.setBackground(Const.COLOR_BGR_LABEL);
			txtShutdownMM.setBackground(Const.COLOR_BGR_LABEL);
			setDisplayControlLabel();
			
			startCountdown();
		}
		else {
			stopCountdown();
			//
			chkEdit.setEnabled(true);
			txtShutdownHH.setEditable(true);
			txtShutdownMM.setEditable(true);
			txtShutdownHH.setBackground(Const.COLOR_TEXT_MUST_INPUT);
			txtShutdownMM.setBackground(Const.COLOR_TEXT_MUST_INPUT);
			txtShutdownHH.selectAll();
			txtShutdownHH.setFocus();
			setDisplayControlLabel();
		}
	}
	
	/**
	 * hide Action
	 *
	 */
	private void hideAction() {
		log.info("Close app & hide to system tray.");
		//
		stopCountdown();
		//
		this.hour = txtShutdownHH.getText().trim();
		this.minute = txtShutdownMM.getText().trim();
		this.day = txtYmd.getText().trim();
		//
		shell.dispose();
		// hide to system tray
		SysTray tray = new SysTray(this.day, this.hour, this.minute);
		tray.open();
	}

	/**
	 * start countdown
	 */
	private void startCountdown(){
		this.hour = txtShutdownHH.getText().trim();
		this.minute = txtShutdownMM.getText().trim();
		this.day = txtYmd.getText().trim();
		if (!Utils.isNullEmpty(this.hour) 
				&& !Utils.isNullEmpty(this.minute) 
				&& !Utils.isNullEmpty(this.day)) {
			log.info("Countdown start.");
			countdown = new CountdownAction(this.day, this.hour, this.minute);
			countdown.run();
		}
	}
	
	/**
	 * stop countdown
	 *
	 */
	private void stopCountdown(){
		if (null != countdown){
			log.info("Countdown stop.");
			countdown.dispose();
		}
	}
	
	/**
	 * checkInput
	 * @return boolean
	 */
	private boolean checkInput() {
		
		Date sys = new Date();
		String sysdate = Utils.formatDate(sys, Const.DATE_FORMAT);
		
		if (txtYmd.getEditable()){
			if (Utils.isNullEmpty(txtYmd.getText())){
				if (language.equals(Const.LANGUAGE_EN)) {
					Utils.errorMsgBox("Day must be input.");
				}
				else {
					Utils.errorMsgBox("Ngày phải được nhập.");
				}
				txtYmd.setFocus();
				return false;
			}
			if (!Utils.isValidDate(txtYmd.getText(), Const.DATE_FORMAT)){
				if (language.equals(Const.LANGUAGE_EN)) {
					Utils.errorMsgBox("Date format must be " + Const.DATE_FORMAT + ".");
				}
				else {
					Utils.errorMsgBox("Phải nhập đúng format ngày " + Const.DATE_FORMAT + ".");
				}
				txtYmd.setFocus();
				return false;
			}
			if (!Utils.compareYYYYMMDD(txtYmd.getText().trim(), sysdate, true)){
				if (language.equals(Const.LANGUAGE_EN)) {
					Utils.errorMsgBox("Input date must be equal or later than today.");
				}
				else {
					Utils.errorMsgBox("Ngày nhập phải lớn hôn hoặc bằng ngày hiện tại.");
				}
				txtYmd.setFocus();
				return false;
			}
		}
		if (Utils.isNullEmpty(txtShutdownHH.getText())){
			if (language.equals(Const.LANGUAGE_EN)) {
				Utils.errorMsgBox("Hour must be input");
			}
			else {
				Utils.errorMsgBox("Giờ phải được nhập.");
			}
			txtShutdownHH.setFocus();
			return false;
		}
		if (!Utils.isNumeric(txtShutdownHH.getText())){
			if (language.equals(Const.LANGUAGE_EN)) {
				Utils.errorMsgBox("Hour must be numeric.");
			}
			else {
				Utils.errorMsgBox("Giờ phải là kiểu số.");
			}
			txtShutdownHH.setFocus();
			return false;
		}
		int hh = Integer.parseInt(txtShutdownHH.getText());
		if (hh < 0 || hh >= 24){
			if (language.equals(Const.LANGUAGE_EN)) {
				Utils.errorMsgBox("Input hour must be in [0, 23].");
			}
			else {
				Utils.errorMsgBox("Giá trị giờ phải nằm trong [0, 23].");
			}
			txtShutdownHH.setFocus();
			return false;
		}
		if (Utils.isNullEmpty(txtShutdownMM.getText())){
			if (language.equals(Const.LANGUAGE_EN)) {
				Utils.errorMsgBox("Minute must be input.");
			}
			else {
				Utils.errorMsgBox("Phút phải được nhập.");
			}
			txtShutdownMM.setFocus();
			return false;
		}
		if (!Utils.isNumeric(txtShutdownMM.getText())){
			if (language.equals(Const.LANGUAGE_EN)) {
				Utils.errorMsgBox("Minute must be numeric.");
			}
			else {
				Utils.errorMsgBox("Phút phải là kiểu số.");
			}
			txtShutdownMM.setFocus();
			return false;
		}
		int mm = Integer.parseInt(txtShutdownMM.getText());
		if (mm < 0 || mm >= 60){
			if (language.equals(Const.LANGUAGE_EN)) {
				Utils.errorMsgBox("Input minute must be in [0, 59].");
			}
			else {
				Utils.errorMsgBox("Giá trị giờ phải nằm trong [0, 59].");
			}
			txtShutdownMM.setFocus();
			return false;
		}
		//
		if (txtYmd.getText().trim().equals(sysdate)){
			String hhmm = Utils.formatDate(sys, "HHmm");
			String input = txtShutdownHH.getText() + txtShutdownMM.getText();
			if (Integer.parseInt(input) <= Integer.parseInt(hhmm)){
				if (language.equals(Const.LANGUAGE_EN)) {
					Utils.errorMsgBox("Input timer must be later than current timer.");
				}
				else {
					Utils.errorMsgBox("Phải nhập giờ lớn hơn giờ hiện tại.");
				}
				txtShutdownHH.setFocus();
				return false;
			}
		}
		//
		return true;
	}
}
